package br.com.abril.job;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import br.com.abril.job.Job.JobType;
import br.com.abril.job.Job.StatusType;

@Service
public class Scheduler {

	private Integer poolSize;

	private ScheduledThreadPoolExecutor executor;

	@Autowired
	private JobRepository repository;

	public Scheduler() {
	}

	@PostConstruct
	public void init() {
		executor = new ScheduledThreadPoolExecutor(10);
		registerJobs();
	}

	@Transactional
	public void registerJobs() {
		for (Job job : repository.findAvailableToSchedule()) {
			add(job);
		}
	}

	@Transactional
	public Job add(Job job) {

		if (job.getType().equals(Job.JobType.RUN_ONE_A_DAY)) {
			executor.schedule
			(job.getCommandClassInstance(),
					job.calculateStartDelayInMiliseconds(),
					TimeUnit.MILLISECONDS);

		} else if (job.getType().equals(Job.JobType.PERIODIC)) {
			executor.scheduleAtFixedRate(job.getCommandClassInstance(),
					job.calculateStartDelayInMiliseconds(), job.getInterval(),
					job.getTimeUnit());
		}

		repository.save(job);

		return job;
	}

	public void shutdown() {
		executor.shutdownNow();
	}

	public ScheduledThreadPoolExecutor getExecutor() {
		return executor;
	}

	@Transactional(readOnly = true)
	public List<Job> buildMigrationJobsFromTemplate(Job template) {
		List<Job> jobsTemplate = repository.findByTemplateTrue();
		List<Job> jobs = new ArrayList<Job>();
		try {
		
			for (Job jobTemplate: jobsTemplate) {
				// clear id to store new Job	
				Job job = jobTemplate.clone();
				job.setActive(true);
				job.setTemplate(false);
				job.setStatus(StatusType.CREATED);
				job.setStartDate(template.getStartDate());
				jobs.add(job);
			}
		
		} catch (CloneNotSupportedException e) {
		}	
		
		return jobs;
	}

	@Transactional
	public List<Job> registerJobsFromTemplate(Job template) {

		List<Job> jobs = buildMigrationJobsFromTemplate(template);
		repository.save(jobs);
		
		registerJobs();
		return jobs;
	}

	public JobRepository getAll() {
		return repository;
	}

	public void reStartJobs() {
		shutdown();
		init();
	}
}
